package com.atguigu.yygh.user.controller;/*
 * @author: XueYouPeng
 * @time: 2023/6/13 19:39
 */


import com.alibaba.fastjson.JSONObject;
import com.atguigu.common.result.Result;
import com.atguigu.exphandler.YyghException;
import com.atguigu.utils.JwtHelper;
import com.atguigu.yygh.enums.AuthStatusEnum;
import com.atguigu.yygh.model.user.UserInfo;
import com.atguigu.yygh.user.config.ConstantPropertiesUtil;
import com.atguigu.yygh.user.service.UserInfoService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.client.RestTemplate;

import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import java.util.HashMap;
import java.util.Map;

@Controller //注意：不是@RestController
@RequestMapping("/api/user/wx")
public class WeixinApiController {

    //springweb中的一个工具类，需要加载到spring容器中，用于在java代码中发起http请求
    @Autowired
    RestTemplate restTemplate;

    @Autowired
    UserInfoService userInfoService;

    /**
     * 点击“第三方登录”按钮时调用，给前端返回一些WxLogin对象需要使用的必要参数
     * @return
     */
    @ResponseBody
    @GetMapping("getLoginParam")
    public Result getLoginParam() throws UnsupportedEncodingException {

        Map<String,Object> map = new HashMap<>();
        map.put("self_redirect",true);//小窗口重定向（扫码后点了确定），重定向到redirect_uri（回调接口），小窗口重定向
        map.put("id","weixinLogin");//前端弹出窗，显示二维码的容器的id
        map.put("appid", ConstantPropertiesUtil.APP_ID);
        map.put("scope","snsapi_login");
        String encode = URLEncoder.encode(ConstantPropertiesUtil.REDIRECT_URL, "utf-8");
        map.put("redirect_uri",encode);//重定向地址(扫码二维码后点击允许，自动重定向到回调接口)，需要进行UrlEncode

        return Result.ok().data(map);

    }

    /**
     * 重定向的接口需求：
     *
     * 1、该接口需要接收一个参数code（微信端生成的一个临时票据）  url?code=xxxx
     * 2、这个临时票据的作用？ 为了后续调用微信端接口获取openid 和 nickname
     * 3、业务需求： 判断该openid在user_info表中是否存在，如果不存在，则利用openid和nickname自动注册
     * 4、判断用户的status=0被锁定，不允许登录，抛出异常
     *
     * 5、判断当前微信用户是否需要绑定手机号
     *
     *      name和token的生成规则和以前一致，如果需要绑定手机号，openid=实际的openid，反之open="空字符串"
     * 6、return ： redirect:http://localhost:3000/weixin/callback?name=xx&token=xx&openid=xxx
     *    重定向到前端的一个vue页面
     *
     *
     *      前端：绑定手机号  or   直接登录成功（name token 写入cookie中）
     * @return
     */
    //自动调用的，在swagger中没有办法测试
    //注意：code不是我们自己生成的
    @GetMapping("callback")
    public String callback(String code) throws UnsupportedEncodingException {

        //1、通过code获取access_token和openid
        String url = "https://api.weixin.qq.com/sns/oauth2/access_token?" +
                "appid=" + ConstantPropertiesUtil.APP_ID +
                "&secret=" + ConstantPropertiesUtil.APP_SECRET +
                "&code=" + code +
                "&grant_type=authorization_code";

        String str1 = restTemplate.getForObject(url, String.class);
        JSONObject jsonObject = JSONObject.parseObject(str1);

        String access_token = jsonObject.getString("access_token");
        String openid = jsonObject.getString("openid");

        //2、通过access_token和openid获取nickname微信昵称
        String url2 = "https://api.weixin.qq.com/sns/userinfo?" +
                "access_token=" + access_token +
                "&openid=" + openid;

        String str2 = restTemplate.getForObject(url2, String.class);
        JSONObject jsonObject2 = JSONObject.parseObject(str2);

        String nickname = jsonObject2.getString("nickname");

        //3、根据openid去user_info表查询该微信用户是否存在，如果不存在，自动注册
        UserInfo userInfo = userInfoService.selectByOpenId(openid);
        if (userInfo==null){
            userInfo = new UserInfo();
            userInfo.setOpenid(openid);
            userInfo.setNickName(nickname);
            //0未认证
            userInfo.setAuthStatus(AuthStatusEnum.NO_AUTH.getStatus());
            //正常（非锁定）
            userInfo.setStatus(1);
            boolean save = userInfoService.save(userInfo);
            if (!save){
                throw new YyghException(20001,"微信用户自动注册失败");
            }
        }

        //4、判断用户的状态status=0 被锁定，不允许登录，抛出异常
        if (userInfo.getStatus()==0){
            throw new YyghException(20001,"该用户被锁定，不允许登录");
        }

        String name = userInfo.getName();
        if (StringUtils.isEmpty(name)) {
            name = userInfo.getNickName();
            if (StringUtils.isEmpty(name)) {
                name = userInfo.getPhone();
            }
        }

        String token = JwtHelper.createToken(userInfo.getId(), name);

        //5、判断微信用户是否需要绑定手机号，检查phone字段是否为空
        if (StringUtils.isEmpty(userInfo.getPhone())){
            //需要绑定手机号
            //6、return（重定向到前端的一个vue页面）
            //如果需要绑定手机号，openid=xx实际的openidxxx ；  如果不需要绑定手机号openid=空字符串
            return "redirect:http://localhost:3000/weixin/callback?name="+name+"&token="+token+"&openid=" + openid;//pages/weixin/callback.vue
        }else {
            //不需要绑定手机号
            //6、return（重定向到前端的一个vue页面）
            //如果需要绑定手机号，openid=xx实际的openidxxx ；  如果不需要绑定手机号openid=空字符串
            return "redirect:http://localhost:3000/weixin/callback?name="+name+"&token="+token+"&openid=" + "";//pages/weixin/callback.vue
        }
    }
}
